CloudFormationでAmazon MemoryDB for Redisのリソースを管理する
コンサル部のとばち(@toda_kk)です。
2021年8月に発表された新サービスであるAmazon MemoryDB for Redisについて、CloudFormationを使ってリソース管理できるようになりました。
Amazon MemoryDB for Redisは、高速なインメモリデータベースでありつつデータの永続化をサポートしているRedis互換のマネージドサービスです。詳細は下記ページをご参照ください。
なお、2021年10月からは東京リージョンでも利用可能になっています。
Amazon MemoryDB for RedisのCloudFormationリソースタイプ
公式ドキュメントが公開されたので、早速眺めてみます。
2021年11月2日現在、サポートされているCloudFormationのリソースタイプは下記の通りです。
- AWS::MemoryDB::ACL
- AWS::MemoryDB::Cluster
- AWS::MemoryDB::ParameterGroup
- AWS::MemoryDB::SubnetGroup
- AWS::MemoryDB::User
Cluster、ParameterGroup、SubnetGroup
MemoryDB for Redisは、ElastiCache for Redisと同様にVPC内に配置されるリソースであり、サブネットグループによって配置するAvailability Zoneやサブネットを指定し、パラメーターグループによってRedisエンジンのパラメーターを設定します。
また、クラスターモードのみがサポートされており、シャード数(NumShards
)やレプリカ数(NumReplicasPerShard
)を指定する必要があります。レプリカ数を1以上で設定する場合は、指定するサブネットグループに複数のAZが含まれている必要があります。
ACL
MemoryDB for Redisではセキュリティグループをサポートしていますが、それとは別にアクセスコントロールリスト(ACL)という形でユーザー毎のアクセス制御を設定できます。
このACLは、Redisバージョン6にて標準でサポートされている機能です。Redis ACL
コマンドを通じて、ユーザーやユーザーグループを作成し、実行可能なコマンドやデータのアクセス制御を設定することができます。
ただし、MemoryDB for RedisにおいてはACL
コマンドの機能は一部制限されており、ユーザーの作成や権限の変更といった書き込みベースの処理がサポートされていません。そのため、ユーザー作成といった操作を実行したいときは、MemoryDB for Redisの機能としてマネジメントコンソールやCLIやCloudFormationから行う必要があります。
redis-cliでRedisに接続した後、ACL HELP
を実行することでサポートされているコマンドを確認できます。まずは、Redisバージョン6のコンテナイメージを引っ張ってきてローカル環境などで起動した上で、素のRedisでサポートされているコマンドを確認してみます。
$ sudo docker pull redis:6 $ sudo docker run -d -p 6379:6379 redis:6 $ redis-cli -h localhost localhost:6379> ACL HELP 1) ACL <subcommand> [<arg> [value] [opt] ...]. Subcommands are: 2) CAT [<category>] 3) List all commands that belong to <category>, or all command categories 4) when no category is specified. 5) DELUSER <username> [<username> ...] 6) Delete a list of users. 7) GETUSER <username> 8) Get the user's details. 9) GENPASS [<bits>] 10) Generate a secure 256-bit user password. The optional `bits` argument can 11) be used to specify a different size. 12) LIST 13) Show users details in config file format. 14) LOAD 15) Reload users from the ACL file. 16) LOG [<count> | RESET] 17) Show the ACL log entries. 18) SAVE 19) Save the current config to the ACL file. 20) SETUSER <username> <attribute> [<attribute> ...] 21) Create or modify a user with the specified attributes. 22) USERS 23) List all the registered usernames. 24) WHOAMI 25) Return the current connection username. 26) HELP 27) Prints this help.
次に、MemoryDB for Redisに接続して確認してみます。ちなみに、クラスターの設定でTLS接続を有効にしている場合は--tls
オプションが必要になります。また、クラスターモードで接続したい場合は-c
オプションを付与します。
$ redis-cli -h xxxxxx.cluster-name.xxxxxx.memorydb.ap-northeast-1.amazonaws.com --tls -c xxxxxx.cluster-name.xxxxxx.memorydb.ap-northeast-1.amazonaws.com:6379> ACL HELP 1) ACL <subcommand> [<arg> [value] [opt] ...]. Subcommands are: 2) LIST -- Show user details in config file format. 3) USERS -- List all the registered usernames. 4) GETUSER <username> -- Get the user details. 5) CAT -- List available categories. 6) CAT <category> -- List commands inside category. 7) GENPASS [<bits>] -- Generate a secure user password. 8) WHOAMI -- Return the current connection username. 9) LOG [<count> | RESET] -- Show the ACL log entries. 10) HELP 11) Prints this help.
素のRedisと比べて、MemoryDB for Redisではサポートされているコマンドが少ないことがわかります。
これはElastiCache for Redisでも同様です。Redis標準ではAUTH
コマンドによるユーザー認証がサポートされていますが、より柔軟な権限制御の方法としてRBAC(Role-Based Access Control)という形でRedis ACL
をサポートしています。
- Authenticating users with the Redis AUTH command - Amazon ElastiCache for Redis
- Authenticating users with Role-Based Access Control (RBAC) - Amazon ElastiCache for Redis
Redisでは当初からAUTH
コマンドによる認証がサポートされていたのですが、バージョン6からAUTH
の拡張と共にACL
が追加され、より柔軟な権限制御を実現できるようになったという背景があります。ElastiCache for RedisではRedisエンジンのバージョン6をサポートするにあたり、RBACという形でRedis ACL
を提供するようになりました。
これを受けて、MemoryDB for RedisではCloudFormationのリソースタイプにもあるようにACL
とUser
をAWSリソースとして管理できるようにサポートしているようです。デフォルトではopen-access
という名前のACLが作成されており、default
ユーザーが登録されています。
User
上述のACLで管理するユーザーを作成するリソースタイプです。形式は下記のようになっています。
Type: AWS::MemoryDB::User Properties: AccessString: String AuthenticationMode: Json Tags: - Tag UserName: String
AccessString
は、ユーザーに許可する操作権限を指定するパラメーターです。on ~* &* +@all
といった形式で記述します。詳細は前掲の MemoryDB for Redisのドキュメント もしくは Redisの公式ドキュメント をご参照ください。
AuthenticationMode
はJSON形式で指定します。MemoryDBにおけるアクションCreateUser
のAPIリファレンスによると、Type
とPasswords
を指定する必要がありそうです。
ここで、上述のdefault
ユーザーの設定値をAWS CLIから確認してみます。すると、Authentication.Type
がno-password
となっていることがわかります。
これはつまり、パスワードなしでRedisに接続できるユーザーということになります。ElastiCache for Redisの場合でも、AUTH認証やRBACのことを特に意識していない状態で利用していれば、このdefault
ユーザーを使ってアクセスしていることになります。
$ aws memorydb describe-users { "Users": [ { "Name": "default", "Status": "active", "AccessString": "on ~* &* +@all", "ACLNames": [ "open-access" ], "MinimumEngineVersion": "6.0", "Authentication": { "Type": "no-password" }, "ARN": "arn:aws:memorydb:ap-northeast-1:123456789012:user/default" } ] }
しかし、データタイプAuthenticationMode
のリファレンスを参照すると、次のような記載があります。
Indicates whether the user requires a password to authenticate. All newly-created users require a password.
つまり、新たにユーザーを作成する場合はパスワードが必要になり、no-password
は実態としてはdefault
ユーザーでしか利用できないようです。
CloudFormationからリソース作成してみる
必要なリソースタイプがわかったので、CloudFormationを使って一通りのリソースを作成してみます。以下は、簡単なサンプルとしてご利用いただければと思います。
AWSTemplateFormatVersion: '2010-09-09' Resources: SampleCluster: Type: AWS::MemoryDB::Cluster Properties: ClusterName: sample-cluster ACLName: !Ref SampleACL NodeType: db.r6g.large NumReplicasPerShard: 1 NumShards: 1 ParameterGroupName: !Ref SampleParameterGroup SecurityGroupIds: - sg-xxxxxxxxxxxxxxxxx - sg-yyyyyyyyyyyyyyyyy SubnetGroupName: !Ref SampleSubnetGroup TLSEnabled: true SampleSubnetGroup: Type: AWS::MemoryDB::SubnetGroup Properties: SubnetGroupName: sample-subnet-group SubnetIds: - subnet-xxxxxxxxxxxxxxxxx - subnet-yyyyyyyyyyyyyyyyy - subnet-zzzzzzzzzzzzzzzzz SampleParameterGroup: Type: AWS::MemoryDB::ParameterGroup Properties: ParameterGroupName: sample-parameter-group Family: memorydb_redis6 SampleACL: Type: AWS::MemoryDB::ACL Properties: ACLName: sample-acl UserNames: - !Ref SampleUser SampleUser: Type: AWS::MemoryDB::User Properties: UserName: sample-user AccessString: on ~* &* +@all AuthenticationMode: { Type: password, Passwords: [xxxxxxxxxxXXXXX!] }
意図した通りにリソースが作成されていました。
以上、コンサル部のとばち(@toda_kk)でした。